/*
 * ClassifiedDataSet.java
 */
package org.osdtsystem.dataset;

import org.osdtsystem.hierarchy.HClass;
import org.osdtsystem.hierarchy.Hierarchy;
import java.util.Comparator;
import java.util.List;
import org.osdtsystem.options.CoverOptions;

/**
 * A classification of a dataset. The classification is itself a collection
 * of hierarchy classes ordered by increasing depth.
 *
 * The dataset is classified by means of a
 * particular hierarchy at a particular class in the hierarchy, down to
 * a certain depth. The classification is not necessarily complete, but may
 * prune the possible classifications by excluding possible classes
 * on the basis of the number of datapoints in the class, etc.
 *
 * @param <H> The type of the classes in the hierarchy.
 * @author Martin Haulrich and Matthias Buch-Kromann
 */
public interface Classification<H extends HClass> {
    /**
     * The hierarchy used for the classification.
     * @return the underlying hierarchy
     */
    public Hierarchy<H> hierarchy();

    /**
     * The root class of the classification.
     * @return the root class
     */
    public H rootClass();

    /**
     * The number of classes in the classification.
     * @return the number of classes in the classification
     */
    public int size();

    /**
     * The size of the class in the classification. This is the number of data
     * points that fall within the class.
     * @param hclass the class
     * @return the size of the class
     */
    public int classSize(H hclass);

    /**
     * The maximal class size in the classification. This is the largest class size
     * that has ever been assigned to any class in the classification, even if the
     * class has subsequently been removed or filtered with a removed data set.
     * @return the maximal class size
     */
    public int maximalClassSize();

    /**
     * The cumulative class size in the classification. This is the sum of all
     * the class sizes in the classification. The number can be used to gauge
     * the complexity of the classification. If the classifications are
     * few and orthogonal with a small class size, this number will be small.
     * If the classifications are many and overlapping with many data points,
     * this number will be large. The cumulative class size is not updated
     * automatically when a dataset is removed from the classification, and in
     * this case, the reported number may exceed the actual number. The correct
     * number can be computed by calling <code>filterAll</code> first, a
     * computationally extensive call.
     * @return the cumulative class size
     */
    public int cumulativeClassSize();

    /**
     * The class weight associated with a class. This is the sum of the weights
     * assigned to all data points that fall within the class.
     * @param hclass the class
     * @return the cumulative weight of the data points in the class
     */
    public double classWeight(H hclass);

    /**
     * The maximal class weight in the classification. This is the largest class weight
     * that has ever been assigned to any class in the classification, even if the
     * class has subsequently been removed or filtered with a removed data set.
     * @return the maximal class weight
     */
    public double maximalClassWeight();

    /**
     * The cumulative class weight. This is the sum of all the class weights
     * in the classification. This number can be used to gauge the complexity of
     * the classification. The cumulative class weight is not updated
     * automatically when a dataset is removed from the classification, and in
     * this case, the reported number may exceed the actual number. The correct
     * number can be computed by calling <code>filterAll</code> first, a
     * computationally extensive call.
     * @return the cumulative class weight
     */
    public double cumulativeClassWeight();

    /**
     * The depth of the class, relative to the root class.
     * @param hclass the class
     * @return the depth of the class relative to the root class
     */
    public int classDepth(H hclass);

    /**
     * The maximal depth of any class in the classification, relative to
     * the top class.
     * @return the maximal depth
     */
    public int maximalDepth();

    /**
     * The classes at a given depth. 
     * @param depth the depth
     * @return the classes at the given depth
     */
    public List<H> classes(int depth);

    /**
     * The data points associated with the class.
     * @param hclass the class
     * @return the dataset containing the associated data points
     */
    public Dataset dataset(H hclass);

    /**
     * Set new dataset for class that is already in the hierarchy.
     * @param hclass the class
     * @param dataset the new dataset
     */
    public void changeDataset(H hclass, Dataset dataset);

    /**
     * Add a classification. The classification is given by a class with an associated
     * dataset.
     * @param hclass the class
     * @param dataset the associated data set
     */
    public void addClass(H hclass, Dataset dataset);

    /**
     * Record the data point as an instance of the given class.
     * @param hclass the class
     * @param identifier the identifier for the data point
     */
    public void addDataPoint(H hclass, int identifier);

    /**
     * Remove the data point as an instance of the given class.
     * @param hclass the class
     * @param identifier the identifier for the data point
     */
    public void removeDataPoint(H hclass, int identifier);

    /**
     * Trim the data set to its minimal size. This operation should not be called
     * before all data points have been classified. The operation will preserve
     * memory, but may be somewhat slow.
     */
    public void trim();

    /**
     * Remove a classification corresponding to a given class.
     * @param hclass the class
     */
    public void removeClass(H hclass);

    /**
     * Remove a set of datapoints from the classification. This operation
     * schedules the datapoints in the data set for removal from all datasets
     * in the classification. The filtered data set for a class is computed lazily,
     * since the filtering is computationally expensive. In particular, the filtered
     * dataset is computed whenever the <code>dataset</code> method is called.
     * @param dataset the dataset that must be removed from the classification
     */
    public void removeData(Dataset dataset);

    /**
     * Compute the filtered datasets for all classes in the classification.
     * This operation also updates the maximal and cumulative counts, and the
     * maximal and cumulative weights for the classes in the classification.
     * This is a computationally expensive operation, so do not use it unless
     * you really need to.
     */
    public void filterAll();

    /**
     * The parameters associated with the classification.
     * @return the classification parameters
     */
    public CoverOptions parameters();

    /**
     * Is a class marked for pruning from the classification? This checks whether
     * the class is too small with respect to maximal class depth, minimal
     * class size, or minimal relative class size. A class that is marked for
     * pruning is not guaranteed to stay in the classification, even if it may remain
     * in the classification for some time.
     * @param hclass the class
     * @return <code>true</code> if the class is marked for pruning or doesn't exist
     * in the classification, <code>false</code> otherwise.
     */
    public boolean isMarkedForPruning(H hclass);

    /**
     * Prune all classes in the classification that are marked for pruning. This operation
     * may be computationally expensive, and should only be called infrequently in order to
     * release memory.
     */
    public void pruneAll();

    /**
     * Return a list containing the k best classes in the classification. Ie,
     * the k largest classes in the classification with respect to the class
     * comparator. The default comparator sorts the classes in terms of their class size.
     * @param k
     * @return
     */
    public List<H> kBestClasses(int k);

    /**
     * Set the comparator that defines the ordering of the classes in the classification.
     * @param comparator the comparator
     */
    public void setComparator(Comparator<? super H> comparator);

    /**
     * Does the given dataset size fall below the minimal dataset size?
     * @param size the dataset size
     * @return <code>true</code> if the size is smaller than the threshold (reject),
     *  <code>false</code> otherwise (accept).
     */
    public boolean isBelowSizeThreshold(int size);

    /**
     * Does the given relative depth fall below the maximal depth threshold? Ie,
     * should classes with this depth be ignored or not?
     * @param depth the depth relative to the root class in the classification
     * @return <code>true</code> if the depth is below the threshold (reject),
     *  <code>false</code> otherwise (accept).
     */
    public boolean isBelowDepthThreshold(int depth);
    
    /**
     * Return a comparator that compares classes in terms of class size.
     * This is the default comparator for the classification.
     * @return the canonical class size comparator
     */
    public Comparator<H> sizeComparator();

    /**
     * Return a comparator that compares classes in terms of class weight.
     * @return the canonical class weight comparator
     */
    public Comparator<H> weightComparator();


    /**
     * The default maximal class depth. The default can be overridden for
     * specific classifications using the corresponding set-method.
     */
    public static int defaultMaxClassDepth = 20;

    /**
     * The default minimum class size. The default can be overridden for
     * specific classifications using the corresponding set-method.
     */
    public static int defaultMinClassCount = 5;

    /**
     * The default minimal relative class size, expressed as a fraction of the
     * size of the largest class in the classification. The default can be overridden for
     * specific classifications using the corresponding set-method.
     */
    public static double defaultMinRelativeClassSize = 0.001;

}
